#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>

// 1.内存泄漏
void memory_leak(void)
{
    char *p = (char *)malloc(1024);
    memset(p, 0, 1024);
}

// 2.非法地址访问
void invalid_address_access(void)
{
    // uint8_t *p = 0x12345678; # 非法地址
    uint8_t *p = NULL;
    printf("val = %d\n", *p);
}

// 3.非法地址访写
void invalid_address_write(void)
{
    // uint8_t *p = 0x12345678; # 非法地址
    uint8_t *p = NULL;
    *p = 0x12;
}

// 4.越界 读写
void corss_border_read_write(void)
{
    uint32_t a = 0x10;
    uint32_t *p = &a + 0x8;

    // 越界读 -- 程序不崩溃,可能导致逻辑错误
    printf("cross border address read %x\n", *p);

    // 越界写 -- 程序错误
    *p = 0x12345678;
    printf("cross border address write %x\n", *p);
}

// 5.内存泄漏 ctrl+c结束进程提示
void manual_leak_mem(void)
{
    printf("申请3次内存，少释放一次,主动触发 内存泄漏\n");
    int *p_data[3];
    p_data[0] = malloc(sizeof(int));
    p_data[1] = malloc(sizeof(int) * 3);
    p_data[2] = malloc(sizeof(int) * 5);

    free(p_data[0]);
    free(p_data[1]);
    // free(p_data[2]);
}

void test5_mem_leak_stop_by_ctrl_c()
{
    // manual_leak_mem();       // 1.只内存泄漏 1次
    while(1)
    {
        manual_leak_mem();      // 2.内存泄漏 多次
        printf("process running\n");
        sleep(1);
    }
}

int main(int argc, char *argv[])
{
    int opt = 1;
    if (argc > 1)
        opt = atoi(argv[1]);
    
    if(opt == 1)
        memory_leak();
    else if(opt == 2)
        invalid_address_access();
    else if(opt == 3)
        invalid_address_write();
    else if(opt == 4)
        corss_border_read_write();
    else if(opt == 5)
        test5_mem_leak_stop_by_ctrl_c();
    else
        printf("1 内存泄漏\n2 非法地址访问\n3 非法地址访写\n4 越界读写\n5 内存泄漏 ctrl+c结束进程提示\n");

    printf("end -----\n");
    return 0;
}
